package com.zero.ddd.akka.event.publisher.demo.infa.task;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.springframework.stereotype.Component;

import com.zero.ddd.akka.cluster.job.annotations.DistributedJob;
import com.zero.ddd.akka.cluster.job.annotations.JobScheduleTimeout;
import com.zero.ddd.akka.cluster.job.annotations.JobScheduled;
import com.zero.ddd.akka.cluster.job.definition.JobTaskContext;
import com.zero.ddd.akka.cluster.job.definition.TaskResult;
import com.zero.ddd.akka.cluster.job.definition.listener.JustLogJobScheudleTimeoutListener;
import com.zero.ddd.akka.cluster.job.model.vo.JobExecuteType;
import com.zero.ddd.akka.event.publisher.demo.domain.company.CompanyId;
import com.zero.ddd.akka.event.publisher.demo.domain.users.vo.UserId;
import com.zero.helper.GU;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @say little Boy, don't be sad.
 * @name Rezar
 * @time 2023-09-27 03:21:33
 * @Desc 些年若许,不负芳华.
 *
 */
@Slf4j
@Component
public class MultiSubTaskTypeDisTaskDemo {
	
	private static final String SUB_TASK_1 = "SUB_TASK_1";
	private static final String SUB_TASK_2 = "SUB_TASK_2";
	
	/**
	 * 
	 * 拆分大任务至不同实例上执行
	 * 
	 * @param context
	 * @return
	 */
	@DistributedJob(
			// 日志显示可读的任务名称
			jobShowName = "打印所有的公司员工2",
			// 任务调度的类型
			jobExecuteType = JobExecuteType.MAP,
			// 单实例并行的任务执行者数量
			concurrency = 20,
			// spring crontab
			jobScheduled = 
				@JobScheduled(
						fixedDelay = 50000, 
						initialDelay = 3000),
			// 单次调度超时时间
			jobScheduleTimeout = 
					@JobScheduleTimeout(
							timeout = 2, 
							timeoutUnit = TimeUnit.MINUTES, 
							timeoutListener = JustLogJobScheudleTimeoutListener.class))
	public TaskResult logCompanyUsers(
			JobTaskContext context) {
		if (context.isRootTask()) {
			log.info("根任务, taskId:{}", context.getTaskId());
			return TaskResult.map(
					SUB_TASK_1,
					loadAllCompany());
		} else if (context.isTaskOfType(SUB_TASK_1)) {
			CompanyId subCompanyId = 
					context.task(CompanyId.class);
			log.info("二级任务，taskId:{} 公司ID:{}", context.getTaskId(), subCompanyId);
			return TaskResult.map(
					SUB_TASK_2,
					GU.split(
							this.loadAllCompanyUser(subCompanyId),
							10)
					.map(BatchSubTaskCommand::new)
					.collect(Collectors.toList()));
		} else if (context.isTaskOfType(SUB_TASK_2)){
			BatchSubTaskCommand subTaskCommand = 
					context.task(BatchSubTaskCommand.class);
			log.info("三级任务，taskId:{} 公司ID:{}", context.getTaskId(), subTaskCommand);
			subTaskCommand.batchCompanyUserIds
			.forEach(companyAndUser -> {
				log.info("获取到Map任务类型的执行参数:{}", companyAndUser);
			});
		}
		return TaskResult.succ();
	}

	private List<CompanyId> loadAllCompany() {
		return 
				IntStream.range(0, 20)
				.mapToObj(CompanyId::new)
				.collect(Collectors.toList());
	}
	
	private List<CompanyUserSubTask> loadAllCompanyUser(
			CompanyId subCompanyId) {
		return 
				IntStream.range(0, 20)
				.mapToObj(index -> {
					return 
							new CompanyUserSubTask(
									subCompanyId, 
									new UserId(index));
				})
				.collect(Collectors.toList());
	}
	
	@Data
	@NoArgsConstructor
	@AllArgsConstructor
	public static class BatchSubTaskCommand {
		private List<CompanyUserSubTask> batchCompanyUserIds;
	}

	@Data
	@ToString
	@NoArgsConstructor
	@AllArgsConstructor
	public static class CompanyUserSubTask {
		private CompanyId companyId;
		private UserId userId;
	}

}